<?php
namespace laiq;

defined('CORE_PATH') or define('CORE_PATH',__DIR__);
class Laiq 
{
    protected $config = [];

    public function __construct($config) {
        $this->config = $config;
    }

    public function run() {
        \spl_autoload_register([$this, 'loadClass']);
        $this->setReporting();
        $this->removeMagicQuotes();
        $this->unregisterGlobals();
        $this->setDbConfig();
        $this->route();
    }

    // 检测开发环境
    public function setReporting() {
        if (APP_DEBUG == true) {
            \error_reporting(E_ALL);
            \ini_set('display_errors', 'On');
        } else {
            \error_reporting(E_ALL);
            \ini_set('display_errors', 'Off');
            \ini_set('log_errors', 'On');
        }
    }

    // 检测敏感字符并删除
    public function removeMagicQuotes() {
        if (get_magic_quotes_gpc()) {
            $_GET = isset($_GET) ? $this->stripSlashesDeep($_GET ) : '';
            $_POST = isset($_POST) ? $this->stripSlashesDeep($_POST ) : '';
            $_COOKIE = isset($_COOKIE) ? $this->stripSlashesDeep($_COOKIE) : '';
            $_SESSION = isset($_SESSION) ? $this->stripSlashesDeep($_SESSION) : '';
        }
    }

    // 删除敏感字符
    public function stripSlashesDeep($value)
    {
        $value = is_array($value) ? array_map(array($this, 'stripSlashesDeep'), $value) : stripslashes($value);
        return $value;
    }

    // 检测自定义全局变量并移除。因为 register_globals 已经弃用，如果
    // 已经弃用的 register_globals 指令被设置为 on，那么局部变量也将
    // 在脚本的全局作用域中可用。 例如， $_POST['foo'] 也将以 $foo 的
    // 形式存在，这样写是不好的实现，会影响代码中的其他变量。 相关信息，
    // 参考: http://php.net/manual/zh/faq.using.php#faq.register-globals
    public function unregisterGlobals()
    {
        if (ini_get('register_globals')) {
            $array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
            foreach ($array as $value) {
                foreach ($GLOBALS[$value] as $key => $var) {
                    if ($var === $GLOBALS[$key]) {
                        unset($GLOBALS[$key]);
                    }
                }
            }
        }
    }

    // 配置数据库信息
    public function setDbConfig()
    {
        if ($this->config['db']) {
            define('DB_HOST', $this->config['db']['host']);
            define('DB_NAME', $this->config['db']['dbname']);
            define('DB_USER', $this->config['db']['username']);
            define('DB_PASS', $this->config['db']['password']);
        }
    }

    public function route() {
        $controllerName = $this->config['defaultController'];
        $actionName = $this->config['defaultAction'];
        $param = array();

        $url = $_SERVER['REQUEST_URI'];
        // 截取?前
        $position = strpos($url, '?');
        $url = $position === false ? $url : substr($url, 0, $position);
        // 删除多余/
        $url = trim($url, '/');

        if ($url) {
            $urlArr = explode('/', $url);
            $urlArr = array_filter($urlArr);

            $controllerName = ucfirst($urlArr[0]);
            array_shift($urlArr);
            $actionName = $urlArr ? $urlArr[0] : $actionName;

            array_shift($urlArr);
            $param = $urlArray ? $urlArray : array();
        }

        //judge controller & action exist
        $controller = 'app\\controllers\\'.$controllerName.'Controller';
        if (!class_exists($controller)) {
            exit($controller . '控制器不存在');
        }
        if (!method_exists($controller, $actionName)) {
            exit($actionName . '方法不存在');
        }

        $dispatch = new $controller($controllerName, $actionName);

        \call_user_func([$dispatch, $actionName], $param);
    }

    // 自动加载类
    public function loadClass($className) {
        $classMap = $this->classMap();

        if (isset($classMap[$className])) {
            $file = $classMap[$className];
        } elseif (strpos($className, '\\') !== false) {
            $file = APP_PATH . str_replace('\\', '/', $className).'.php';
            if (!is_file($file)) {
                return;
            }
        } else {
            return;
        }

        include $file;
    }

    protected function classMap() {
        return [
            'laiq\base\Controller' => CORE_PATH . '/base/Controller.php',
            'laiq\base\Model' => CORE_PATH . '/base/Model.php',
            'laiq\base\View' => CORE_PATH . '/base/View.php',
            'laiq\db\Db' => CORE_PATH . '/db/Db.php',
            'laiq\db\Sql' => CORE_PATH . '/db/Sql.php'
        ];
    }
}